<template>
  <div
    class="page_root"
    :key="queryUpdateFlag"
    data-page-name="1"
    data-page-identification="x_hb0xe6o0k2"
  >
    <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
      <!-- begin vid_q2pj193dfc 自定义模板_7xu4mdl9mj -->
      <!--          新建编辑模板-->
      <a-modal
        :visible="templateState.templateModalVisible"
        :title="templateState.modalTitle"
        @ok="confirmGdTemplate"
        @cancel="cancelGdTemplate"
        centered
        :footer="templateState.isDetail ? null : undefined"
        destroy-on-close
        :ok-button-props="{ loading: templateState.okLoading }"
        width="100%"
        :mask-closable="false"
        :body-style="{
          maxHeight: '800px',
          overflowY: 'auto',
          paddingBottom: 0,
        }"
      >
        <a-form
          :model="templateState.templateModalForm"
          ref="sopMbFormRef"
          :rules="templateState.templateFormRole"
        >
          <div class="sop-modal">
            <a-row :gutter="12">
              <a-col :span="24">
                <div :class="{ 'readonly-wrapper': templateState.isDetail }">
                  <a-row>
                    <a-col :span="24">
                      <a-form-item
                        label="工单模板名称"
                        name="templateName"
                        :rules="templateState.templateFormRole.templateName"
                      >
                        <a-input
                          v-model:value="
                            templateState.templateModalForm.templateName
                          "
                          placeholder="请输入"
                          maxlength="50"
                          show-count
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="6">
                      <a-form-item
                        label="工单类型"
                        :rules="templateState.templateFormRole.type"
                        name="type"
                      >
                        <a-select
                          show-search
                          :options="templateState.workTypeList"
                          v-model:value="templateState.templateModalForm.type"
                          placeholder="请选择"
                          :field-names="{ label: 'label', value: 'value' }"
                          :filterOption="
                            (input, option) => {
                              return (
                                option.label
                                  .toLowerCase()
                                  .indexOf(input.toLowerCase()) >= 0
                              );
                            }
                          "
                          @change="hanldeTypeChange(true)"
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="6">
                      <a-form-item
                        label="监控场景"
                        :rules="templateState.templateFormRole.monitorScene"
                        name="monitorScene"
                      >
                        <a-select
                          @focus="getMonitorSceneList(false)"
                          show-search
                          :options="templateState.monitorSceneList"
                          v-model:value="
                            templateState.templateModalForm.monitorScene
                          "
                          placeholder="请选择"
                          :field-names="{ label: 'label', value: 'value' }"
                          :filterOption="
                            (input, option) => {
                              return (
                                option.label
                                  .toLowerCase()
                                  .indexOf(input.toLowerCase()) >= 0
                              );
                            }
                          "
                          @change="moChange"
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="6">
                      <a-form-item
                        label="工单owner"
                        :rules="templateState.templateFormRole.owner"
                        name="owner"
                      >
                        <a-select
                          show-search
                          allow-clear
                          :options="templateState.allUser"
                          v-model:value="templateState.templateModalForm.owner"
                          placeholder="请选择"
                          :field-names="{ label: 'name', value: 'name' }"
                          :filter-option="
                            (input, option) => {
                              return (
                                option.name
                                  .toLowerCase()
                                  .indexOf(input.toLowerCase()) >= 0
                              );
                            }
                          "
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="6">
                      <a-form-item
                        label="父工单解决人"
                        :rules="templateState.templateFormRole.solver"
                        name="owner"
                      >
                        <a-select
                          show-search
                          allow-clear
                          :options="templateState.allUser"
                          v-model:value="templateState.templateModalForm.solver"
                          placeholder="请选择"
                          :field-names="{ label: 'name', value: 'name' }"
                          :filter-option="
                            (input, option) => {
                              return (
                                option.name
                                  .toLowerCase()
                                  .indexOf(input.toLowerCase()) >= 0
                              );
                            }
                          "
                        />
                      </a-form-item>
                    </a-col>
                  </a-row>
                </div>
              </a-col>
              <a-col :span="24">
                <div class="modal-sop-title">SOP配置</div>
              </a-col>

              <a-col :span="24">
                <div class="flow-content">
                  <!-- 主体部分：左中右 -->
                  <div class="flow-container">
                    <!-- 画布 -->
                    <div
                      class="flow-area"
                      @drop="onDrop"
                      @dragover="onDragOver"
                    >
                      <VueFlow
                        v-model:nodes="nodes"
                        v-model:edges="edges"
                        @node-click="onNodeClick"
                        @connect="onConnect"
<<<<<<< HEAD
=======
                         @pane-click="handlePaneClick"
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
                        :selectEdgesOnClick="true"
                      >
                        <template #edge-default="props">
                          <BaseEdge
                            :id="props.id"
                            :path="
                              getStraightPath({
                                sourceX: props.sourceX,
                                sourceY: props.sourceY,
                                targetX: props.targetX,
                                targetY: props.targetY,
                              })[0]
                            "
                            :label-x="(props.sourceX + props.targetX) / 2"
                            :label-y="(props.sourceY + props.targetY) / 2"
                            label-bg-style="fill: whitesmoke"
                          />
                          <foreignObject
                            :x="(props.sourceX + props.targetX) / 2 - 30"
                            :y="(props.sourceY + props.targetY) / 2 - 20"
                            width="20"
                            height="20"
                            class="edge-delete-fo"
                          >
                            <div
                              class="edge-delete-btn"
                              v-if="props.selected"
                              @click.stop="removeEdge(props.id)"
                            >
                              <DeleteOutlined
                                style="color: #8a94a5; font-size: 20px"
                              />
                            </div>
                          </foreignObject>
                        </template>

                        <!--                        自定义节点-->
                        <template #node-start="nodeProps">
                          <div class="custom-node">
                            <div class="handle">
                              <handle type="source" position="right" />
                            </div>
                            <div class="node-content">
                              {{ nodeProps.data.label }}
                            </div>
                          </div>
                        </template>
                        <template #node-input="nodeProps">
                          <div
                            class="node-hover-wrapper"
                            :class="{
                              'node-hover-active': hoverNodeId === nodeProps.id,
                            }"
                          >
                            <div
                              class="custom-node"
                              @mouseenter="hoverNodeId = nodeProps.id"
                              @mouseleave="hoverNodeId = null"
                            >
                              <handle type="target" position="left" />
                              <div
                                class="node-line"
                                :title="nodeProps.data.sopStep"
                                :style="getBacColor(nodeProps)"
                              >
                                {{
                                  nodeProps.data.sopStep || "点击编辑SOP步骤"
                                }}
                              </div>
                              <handle type="source" position="right" />
                              <div
                                class="node-delete-btn"
                                v-if="nodeProps.selected"
                                @click.stop="removeNode(nodeProps.id)"
                              >
                                <DeleteOutlined
                                  style="color: #8a94a5; font-size: 20px"
                                />
                              </div>
                            </div>
                          </div>
                        </template>
                        <!--                                                <template #node-output="nodeProps">-->
                        <!--                                                    <div class="lf-node-selected">-->

                        <!--                                                        <div class="custom-node">-->
                        <!--                                                            <div class="handle">-->
                        <!--                                                                <handle type="target" position="left" />-->
                        <!--                                                            </div>-->
                        <!--                                                            <div class="node-content">{{ nodeProps.data.label }}</div>-->
                        <!--                                                            <div-->
                        <!--                                                                class="node-delete-btn"-->
                        <!--                                                                v-if="nodeProps.selected"-->
                        <!--                                                                @click.stop="removeNode(nodeProps.id)"-->
                        <!--                                                            >-->
                        <!--                                                                <DeleteOutlined-->
                        <!--                                                                    style="color: #8a94a5; font-size: 20px"-->
                        <!--                                                                />-->
                        <!--                                                            </div>-->
                        <!--                                                        </div>-->
                        <!--                                                    </div>-->
                        <!--                                                </template>-->
                        <template #node-output="nodeProps">
                          <div
                            class="node-hover-wrapper"
                            :class="{
                              'node-hover-active': hoverNodeId === nodeProps.id,
                            }"
                          >
                            <div
                              class="custom-node"
                              @mouseenter="hoverNodeId = nodeProps.id"
                              @mouseleave="hoverNodeId = null"
                            >
                              <div class="handle">
                                <handle type="target" position="left" />
                              </div>
                              <div class="node-content">
                                {{ nodeProps.data.label }}
                              </div>
                              <div
                                class="node-delete-btn"
                                v-if="nodeProps.selected"
                                @click.stop="removeNode(nodeProps.id)"
                              >
                                <DeleteOutlined
                                  style="color: #8a94a5; font-size: 20px"
                                />
                              </div>
                            </div>
                          </div>
                        </template>

                        <Background />
                        <Controls />
                      </VueFlow>
                    </div>
                  </div>
                </div>
              </a-col>
              <a-col :span="24" v-if="isShowForm" class="readonly-wrapper">
                <a-form :model="selectedNode">
                  <a-col :span="24">
                    <a-form-item label="SOP步骤">
                      <a-input
                        placeholder="请输入"
                        maxlength="100"
                        show-count
                        v-model:value="selectedNode.sopStep"
                      />
                    </a-form-item>
                  </a-col>
                  <a-col :span="24">
                    <a-form-item label="解决角色">
                      <a-select
                        allow-clear
                        v-model:value="selectedNode.solverRole"
                        show-search
                        placeholder="请选择"
                      />
                    </a-form-item>
                  </a-col>
                </a-form>
              </a-col>
              <a-col :span="24">
                <div class="modal-sop-title">抄送设置</div>
              </a-col>
              <template
                v-for="(item, index) in templateState.templateModalForm.ccList"
                :key="index"
              >
                <a-col
                  :span="22"
                  :class="{ 'readonly-wrapper': templateState.isDetail }"
                >
                  <a-form-item label="告警级别">
                    <a-select
                      allow-clear
                      :options="templateState.warnLevelList"
                      v-model:value="
                        templateState.templateModalForm.ccList[index].warnLevel
                      "
                      placeholder="请选择"
                      :field-names="{ label: 'label', value: 'label' }"
                      :filter-option="
                        (input, option) => {
                          return (
                            option.name
                              .toLowerCase()
                              .indexOf(input.toLowerCase()) >= 0
                          );
                        }
                      "
                    />
                  </a-form-item>
                </a-col>
                <a-col
                  :span="2"
                  style="padding: 0"
                  v-if="!templateState.isDetail"
                >
                  <a-space :size="8">
                    <a-button
                      size="small"
                      type="link"
                      @click="handleDeleteCc(index)"
                      >删除</a-button
                    >
                  </a-space>
                </a-col>
                <a-col :span="24">
                  <div class="modal-sop-title-no">工单触发抄送人</div>
                </a-col>
                <a-col
                  :span="22"
                  :class="{ 'readonly-wrapper': templateState.isDetail }"
                >
                  <a-form-item label="角色">
                    <a-select
                      allow-clear
                      show-search
                      :options="templateState.ccPeopleList"
                      placeholder="请选择"
                      v-model:value="
                        templateState.templateModalForm.ccList[index]
                          .triggerRoleList
                      "
                      mode="multiple"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                        (input, option) => {
                          return (
                            option.label
                              .toLowerCase()
                              .indexOf(input.toLowerCase()) >= 0
                          );
                        }
                      "
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="24">
                  <div class="modal-sop-title-no">工单超时抄送人</div>
                </a-col>
                <a-col
                  :span="22"
                  :class="{ 'readonly-wrapper': templateState.isDetail }"
                >
                  <a-form-item label="角色">
                    <a-select
                      allow-clear
                      mode="multiple"
                      show-search
                      :options="templateState.ccPeopleList"
                      placeholder="请选择"
                      v-model:value="
                        templateState.templateModalForm.ccList[index]
                          .timeoutRoleList
                      "
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                        (input, option) => {
                          return (
                            option.label
                              .toLowerCase()
                              .indexOf(input.toLowerCase()) >= 0
                          );
                        }
                      "
                    />
                  </a-form-item>
                </a-col>
                <a-divider style="height: 1px; background-color: #d9d9d9" />
              </template>
              <a-col :span="24" v-if="!templateState.isDetail">
                <a-form-item>
                  <a-button
                    type="primary"
                    ghost
                    @click="handleAddCc(index, '下方')"
                    ><template #icon> <plus-outlined /> </template
                    >新增</a-button
                  >
                </a-form-item>
              </a-col>
            </a-row>
          </div>
        </a-form>
      </a-modal>
      <!--          新建编辑模板-->

      <div class="gd-template-body">
        <div class="top-search">
          <a-form :model="templateState.filter">
            <a-row justify="space-between">
              <a-col :span="6">
                <a-form-item
                  label="模板名称"
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                >
                  <a-input
                    v-model:value="templateState.filter.templateName"
                    placeholder="请输入"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item
                  label="工单类型"
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                >
                  <a-select
                    v-model:value="templateState.filter.type"
                    :options="templateState.workTypeList"
                    show-search
                    allow-clear
                    placeholder="请选择"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filterOption="
                      (input, option) => {
                        return (
                          option.label
                            .toLowerCase()
                            .indexOf(input.toLowerCase()) >= 0
                        );
                      }
                    "
                    @change="hanldeTypeChange(false)"
                  />
                </a-form-item>
              </a-col>

              <a-col :span="6">
                <a-form-item
                  label="监控场景"
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                >
                  <a-select
                    v-model:value="templateState.filter.monitorScene"
                    :options="templateState.monitorSceneList"
                    show-search
                    allow-clear
                    placeholder="请选择"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filterOption="
                      (input, option) => {
                        return (
                          option.label
                            .toLowerCase()
                            .indexOf(input.toLowerCase()) >= 0
                        );
                      }
                    "
                    @focus="getMonitorSceneList(true)"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                  label="工单负责人"
                >
                  <a-select
                    show-search
                    allow-clear
                    :options="templateState.allUser"
                    v-model:value="templateState.filter.owner"
                    placeholder="请选择"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                      (input, option) => {
                        return (
                          option.name
                            .toLowerCase()
                            .indexOf(input.toLowerCase()) >= 0
                        );
                      }
                    "
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="6">
                <a-form-item
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                  label="模板创建人"
                >
                  <a-select
                    show-search
                    allow-clear
                    :options="templateState.allUser"
                    v-model:value="templateState.filter.createdBy"
                    placeholder="请选择"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                      (input, option) => {
                        return (
                          option.name
                            .toLowerCase()
                            .indexOf(input.toLowerCase()) >= 0
                        );
                      }
                    "
                  />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item
                  label="模板创建时间"
                  :labelCol="{ span: 7 }"
                  :wrapperCol="{ span: 17 }"
                >
                  <a-range-picker
                    v-model:value="templateState.filter.createdTimeList"
                    value-format="YYYY-MM-DD"
                    style="width: 100%"
                  />
                </a-form-item>
              </a-col>

              <a-col
                :span="12"
                style="display: flex; justify-content: end; align-items: start"
              >
                <a-space>
                  <a-button type="primary" @click="getGdTemplateData(true)"
                    >查询</a-button
                  >
                  <a-button type="primary" ghost @click="resetTemplateData"
                    >重置</a-button
                  >
                </a-space>
              </a-col>
            </a-row>
          </a-form>
        </div>
        <a-spin :spinning="templateState.spin" tip="加载中">
          <div class="template-content">
            <div class="sop-title">
              <div class="sop-title-left">工单模板列表</div>
              <a-button type="primary" ghost @click="handleAddTemplate"
                >新建</a-button
              >
            </div>
            <div class="gd-template-scroll">
              <template v-if="templateState.dataSource.length == 0">
                <div class="no-data-img"></div>
                <div class="no-data-msg">暂无数据</div>
              </template>
              <div
                class="gd-item"
                v-for="(item, index) in templateState.dataSource"
                :key="item.id"
              >
                <a-collapse
                  :bordered="false"
                  expandIconPosition="right"
                  v-model:activeKey="templateState.collapseKey"
                >
                  <template #expandIcon="{ isActive }"> </template>
                  <a-collapse-panel :key="item.templateId">
                    <template #header>
                      <div class="template-item-title">
                        <div class="item-top">
                          <div class="top-left-div">
                            <div class="item-sign">
                              {{ item.type }}
                            </div>
                            <div class="item-name">{{ item.templateName }}</div>
                          </div>
                          <div class="top-right-div" @click.stop="onClick">
                            <a-space :size="8">
                              <a-button
                                v-if="item.status == '已发布'"
                                type="primary"
                                ghost
                                size="small"
                                style="color: #8c8c8c; border-color: #8c8c8c"
                                class="btn-item"
                                @click="publishOffline(item, item.templateId)"
                                >下线
                              </a-button>
                              <a-button
                                v-if="item.status == '待发布'"
                                type="primary"
                                ghost
                                style="color: #52c41a; border-color: #52c41a"
                                size="small"
                                class="btn-item"
                                @click="publishOffline(item, item.templateId)"
                                >发布
                              </a-button>
                              <a-button
                                type="primary"
                                ghost
                                size="small"
                                class="btn-item"
                                @click="handlerEditTemplate(item, false)"
                                >编辑
                              </a-button>
                              <a-button
                                type="primary"
                                ghost
                                size="small"
                                class="btn-item"
                                @click="handlerDetailTemplate(item)"
                                >详情
                              </a-button>
                              <a-popconfirm
                                title="确认删除吗?"
                                ok-text="确定"
                                cancel-text="取消"
                                @confirm="
                                  handlerDeleteTemplate(item.templateId)
                                "
                                @cancel="cancel"
                              >
                                <a-button type="primary" ghost size="small"
                                  >删除</a-button
                                >
                              </a-popconfirm>

                              <div
                                @click.stop="toggleCollapse(item.templateId)"
                              >
                                <!--                                                        <button type="link">-->
                                <!--                                                            -->
                                <!--                                                        </button>-->
                                <span style="color: #3875ff; cursor: pointer">{{
                                  isActive(item.templateId) ? "收起" : "展开"
                                }}</span>
                                <DoubleLeftOutlined
                                  v-if="isActive(item.templateId)"
                                  class="active-icon"
                                />
                                <DoubleRightOutlined
                                  v-else
                                  class="active-icon"
                                />
                              </div>
                            </a-space>
                          </div>
                        </div>
                        <div class="item-bottom">
                          <div class="bottom-top-item">
                            <span class="bottom-top-title">监控场景：</span>
                            <span class="bottom-top-msg">{{
                              item.monitorSceneValue
                            }}</span>
                          </div>
                          <div class="bottom-top-item">
                            <span class="bottom-top-title">模板创建时间：</span>
                            <span class="bottom-top-msg">{{
                              item.createdTime
                            }}</span>
                          </div>
                          <div class="bottom-top-item">
                            <span class="bottom-top-title">模板创建人：</span>
                            <span class="bottom-top-msg">{{
                              item.createdBy
                            }}</span>
                          </div>
                          <div class="bottom-top-item">
                            <span class="bottom-top-title">工单负责人：</span>
                            <span class="bottom-top-msg">{{ item.owner }}</span>
                          </div>
                        </div>
                      </div>
                    </template>
                    <div style="background: rgba(56, 117, 255, 0.1)">
                      <div class="title-border"></div>
                    </div>
                    <!--                           列表父工单-->
                    <div class="item-inner">
                      <div class="modal-sop-title">抄送设置</div>
                      <div class="inner-table">
                        <a-table
                          :columns="noticeColumns"
                          :data-source="item.ccList"
                          bordered
                          :pagination="false"
                        >
                          <template #bodyCell="{ record, text, column, index }">
                            <template v-if="column.fieldType === 'FILE'">
                              <div
                                class="file-div"
                                @dblclick="
                                  showEditStatistics(column, record, index)
                                "
                              >
                                <template v-if="text">
                                  <div
                                    v-for="(item, index) in JSON.parse(text)"
                                    :key="item.name"
                                  >
                                    <a-dropdown>
                                      <a :title="item.name">{{ item.name }}</a>
                                      <template #overlay>
                                        <a-menu>
                                          <a-menu-item
                                            v-if="item.type.startsWith('image')"
                                          >
                                            <a-button
                                              type="link"
                                              size="small"
                                              :disabled="
                                                !item.type.startsWith('image')
                                              "
                                              @click="viewImage(item.url)"
                                              >预览</a-button
                                            >
                                          </a-menu-item>
                                          <a-menu-item>
                                            <a-button
                                              type="link"
                                              size="small"
                                              @click="
                                                downLoadGdTemplateFile(item)
                                              "
                                              >下载</a-button
                                            >
                                          </a-menu-item>
                                        </a-menu>
                                      </template>
                                    </a-dropdown>
                                  </div>
                                </template>
                                <template v-else>
                                  <div class="file-div"></div>
                                </template>
                              </div>
                            </template>
                          </template>
                        </a-table>
                      </div>
                    </div>

                    <!--                           列表父工单-->
                  </a-collapse-panel>
                </a-collapse>
              </div>
            </div>
          </div>
        </a-spin>
      </div>

      <!-- end vid_q2pj193dfc 自定义模板_7xu4mdl9mj -->
    </a-spin>
  </div>
</template>
<script setup lang="tsx">
import {
  h,
  ref,
  reactive,
  toRaw,
  markRaw,
  watch,
  computed,
  onBeforeMount,
  onMounted,
  onBeforeUnmount,
  onUnmounted,
  onActivated,
  onDeactivated,
  nextTick,
} from "vue";
import { useRoute, useRouter } from "vue-router";
const router = useRouter();
const route = useRoute();
import {
  get,
  post,
  put,
  del,
  request,
  requestWithHeaders,
} from "@/utils/http/Axios";
import {
  cloneDeep,
  localGet,
  merge,
  getDifferenceArray,
  traversalTreeStructure,
  checkCaseCondition,
  renderStringInTemplate,
  handleBreadcrumbJump,
  throttle,
  permission,
  getComponentParamsValue,
} from "@/utils";
import {
  isNullOrEmpty,
  isEmptyArr,
  isNullOrUnDef,
  isContained,
  isArray,
  isEmpty,
  isObject,
} from "@/utils/is";
import dayjs from "dayjs";
import { getPagePcChartsDataSourceConvert } from "@/utils/chart";
import { message, notification, Modal } from "ant-design-vue";
import {
  propertyFormatByNumber,
  propertyFormatByPercentage,
  propertyFormatByDate,
  parseSubFromDataList,
} from "@/utils/format";
import colorTheme from "@/design/custom-theme.json";
import { BaseEdge, getStraightPath, Handle, VueFlow } from "@vue-flow/core";
import { Controls } from "@vue-flow/controls";
import { Background } from "@vue-flow/background";
/*** PUBLISH_EXEGESIS ***
 import UserTableRecords from '@/model/UserTableRecords';
 import { getAppBaseUrl } from '@/utils/index';
 import { sendToken } from "@/hooks/useIframeToken";
 import { useSystemStore } from "@/store/modules/system";
 const systemStore = useSystemStore();
 *** PUBLISH_EXEGESIS ***/

// 获取传入的流程ID和组件参数
const props = defineProps({
  processInstanceId: {
    type: [String, Number, Boolean],
    default: undefined,
  },
});
const immediateWatch = (source, callback) => {
  watch(source, callback, { deep: true, immediate: true });
};

/* -------------------------- 属性定义 -------------------------- */

const setTimeOutList = [];
const pageLoading = reactive({
  loading: false,
  tip: undefined,
});
const authInfo = localGet("app-user-store");
const vid_3z78u6tjtg_imageUrl =
  "http://10.40.0.33:9001/file-storage/487394680222738432-source.svg";

const vid_3z78u6tjtg_props = reactive({
  src: vid_3z78u6tjtg_imageUrl,
});

// 处理校验
const setSubFormName = (parentInfo, name) => {
  return [parentInfo.parents, parentInfo.cycleIndex, name];
};

/* ========================== 属性定义 ========================== */

/* -------------------------- 元素数据引用 -------------------------- */

/* ========================== 元素数据引用 ========================== */

/* -------------------------- 页面数据 -------------------------- */

/* ========================== 页面数据 ========================== */

/* -------------------------- 响应 -------------------------- */

/* ========================== 响应 ========================== */

/* -------------------------- 函数 -------------------------- */

/* ========================== 函数 ========================== */

/* -------------------------- 页面参数 -------------------------- */

const pageParameter_templateState = reactive({
  processInstanceId: props.processInstanceId ?? route.query.processInstanceId,
});

/* ========================== 页面参数 ========================== */

/* -------------------------- 组件事件处理方法 -------------------------- */

// ---------------------------- 组件数据同步 ----------------------------

// ============================ 组件数据同步 ============================

/* ========================== 组件事件处理方法 ========================== */

/* -------------------------- 生命周期 -------------------------- */
// 用于参数变更后重新执行自定义指令
const queryUpdateFlag = ref(0);
onMounted(() => {});

onUnmounted(() => {
  // 销毁定时器
  setTimeOutList.forEach(({ repeat, timer }) => {
    repeat ? clearInterval(timer) : clearTimeout(timer);
  });
});

/* ========================== 生命周期 ========================== */

/* -------------------------- 数据关联处理 -------------------------- */

/* -------------------------- 表单数据同步 -------------------------- */
/* ========================== 表单数据同步 ========================== */

/* ========================== 数据关联处理 ========================== */

/* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

/* ========================== 不同组件自定义的处理逻辑 ========================== */

// ================================定制化逻辑========================================
const templateState = reactive({
  filter: {
    templateName: undefined,
    type: undefined,
    monitorScene: undefined,
    owner: undefined,
    createdBy: undefined,
    createdTimeList: undefined,
  },
  dataSource: [],
  templateNameList: [], //模板名称选择
  monitorSceneList: [], //监控场景选择
  allUser: [], //人员
  modalVisible: false,
  collapseKey: [], //展开折叠
  // 工单类型list
  workTypeList: [],
  // 抄送角色list
  ccPeopleList: [],
  // 告警list
  gjList: [],
  // 监控场景
  monitorSceneList: [],
  // 告警级别
  warnLevelList: [],
  templateModalVisible: false,
  modalTitle: "新建工单模板",
  isDetail: false,
  okLoading: false,
  tableLoading: false, //表格lodding
  spin: false, //表格lodding
  templateFormRole: {
    templateName: [
      { required: true, message: "请输入SOP名称", trigger: "blur" },
    ],
    type: [{ required: true, message: "请选择工单类型", trigger: "blur" }],
    monitorScene: [
      { required: true, message: "请选择监控场景", trigger: "blur" },
    ],
    owner: [{ required: true, message: "请选择工单负责人", trigger: "blur" }],
    solver: [
      { required: true, message: "请选择父工单解决人", trigger: "blur" },
    ],
  },
  templateModalForm: {
    templateName: undefined, //sop名称
    finishStandard: undefined, //完成标准
    assessorStandard: undefined, //审核标准
    type: undefined, //工单类型
    monitorScene: undefined, //监控场景
    belongBusiness: undefined, //所属业务
    attachmentTemplateList: undefined, //附件名称
    WorkOrderTemplate: [], //勾选的sop
    ccList: [
      {
        warnLevel: undefined, //告警级别
        role: undefined, //触发抄送人角色
        timeouRole: undefined, //超市抄送角色
      },
    ],
    sopList: [],
    selectedRowKeys: [],
  },
});
onMounted(() => {
  getGdTemplateData();
  getWorkType();
  getAllUser();
  getWarnList();
  getCcPeopleList();
});
//获取列表数据
function getGdTemplateData() {
  templateState.spin = true;
  post(
<<<<<<< HEAD
    "/solution-ppm-work-order/api/v1/work_order_template/search",
=======
    "/solution-ppm/api/v2/built-in-system-ppm/work_order_template/search",
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
    templateState.filter
  )
    .then((data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      templateState.dataSource = data.data.map((item) => {
        return {
          ...item,
          opration: "SOP",
        };
      });
    })
    .finally(() => {
      templateState.spin = false;
    });
}
// 清除
function resetTemplateData() {
  templateState.filter = {
    templateName: undefined,
    type: undefined,
    monitorScene: undefined,
    owner: undefined,
    solver: undefined,
    createdBy: undefined,
    createdTimeList: undefined,
  };
  getGdTemplateData();
}
// 解决角色list
function getCcPeopleList() {
<<<<<<< HEAD
  get("/solution-ppm-work-order/api/v1/work_order_sop/template_role").then(
    (data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      templateState.ccPeopleList = data.data;
    }
  );
=======
  get(
    "/solution-ppm/api/v2/built-in-system-ppm/work_order_sop/template_role"
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    templateState.ccPeopleList = data.data;
  });
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
}
// 获取工单类型字典值
function getWorkType() {
  get(
<<<<<<< HEAD
    "/solution-ppm-work-order/api/v1/work_order_sop/get_work_type_by_monitor_scene"
=======
    "/solution-ppm/api/v2/built-in-system-ppm/work_order_sop/get_work_type_by_monitor_scene"
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    templateState.workTypeList = data.data.map((item) => {
      return {
        label: item.itemName,
        value: item.itemName,
      };
    });
  });
}
// 获取监控场景list
function getMonitorSceneList(flag) {
  console.log(flag);
  const params = flag
    ? templateState.filter.type
    : templateState.templateModalForm.type;
  console.log(params, "params");
  get(
    `/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/${params}`
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    templateState.monitorSceneList = data.data.map((item) => {
      return {
        label: item.itemName,
        value: item.itemCode,
      };
    });
  });
}
// 获取告警级别list
function getWarnList() {
  get(
    "/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.GJJB"
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    templateState.warnLevelList = data.data.map((item) => {
      return {
        label: item.itemName,
        value: item.itemCode,
      };
    });
  });
}
function moChange() {
  templateState.templateModalForm.selectedRowKeys = [];
  getSopList();
}
// 选完场景获取列表
function getSopList() {
<<<<<<< HEAD
  post("/solution-ppm-work-order/api/v1/work_order_sop/search", {
=======
  post("/solution-ppm/api/v2/built-in-system-ppm/work_order_sop/search", {
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
    workType: templateState.templateModalForm.type,
    monitorScene: templateState.templateModalForm.monitorScene,
  })
    .then((data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      if (data.data[0]) {
        nodes.value = JSON.parse(data.data[0].flowChart).chartList;
        edges.value = JSON.parse(data.data[0].flowChart).lineList;
      } else {
        edges.value = [];
        nodes.value = [];
      }
    })
    .finally(() => {
      templateState.tableLoading = false;
    });
}

// 全部人
function getAllUser() {
  get("/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser").then(
    (data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      templateState.allUser = data.data.userDtoList;
    }
  );
}
const toggleCollapse = (id) => {
  console.log("调用 toggleCollapse", id);

  const stringId = String(id);

  if (isActive(stringId)) {
    templateState.collapseKey = templateState.collapseKey.filter(
      (key) => key !== stringId
    );
  } else {
    templateState.collapseKey = [...templateState.collapseKey, stringId];
  }
};

function isActive(id) {
  const stringId = String(id); // 确保 id 为字符串格式
  return templateState.collapseKey.includes(stringId); // 检查该 ID 是否在 collapseKey 中
}
//     删除

function isCloseDisabled(item) {
  return (
    !(
      (item.status === "未开始" && item.solvers) ||
      (item.status === "未开始" && item.myCreated)
    ) &&
    !(item.status === "解决中" && item.solvers) &&
    !(item.status === "已解决" && item.myCreated) &&
    !(item.status === "待分发" && item.distributed)
  ); // 创建人或PMO关闭
}

function isReturnVisitDisabled(item) {
  return !(item.status === "已关闭" && (item.myCreated || item.pmoOrNot)); // 创建人或PMO回访
}
//     删除
const sopColumns = ref([
  {
    title: "SOP名称",
    dataIndex: "sopName",
    align: "center",
    ellipsis: true,
    customCell: ({ rowSpan }) => {
      return {
        rowSpan: rowSpan,
      };
    },
  },
  {
    title: "SOP步骤",
    dataIndex: "sopStep",
    align: "center",
    ellipsis: true,
  },
  {
    title: "附件模板",
    dataIndex: "attachmentTemplateList",
    align: "center",
    ellipsis: true,
    customCell: ({ rowSpan }) => {
      return {
        rowSpan: rowSpan,
      };
    },
  },
  {
    title: "解决角色",
    dataIndex: "solverRole",
    align: "center",
    ellipsis: true,
  },
]);
const noticeColumns = ref([
  {
    title: "告警级别",
    dataIndex: "warnLevel",
    align: "center",
    ellipsis: true,
  },
  {
    title: "触发抄送人",
    dataIndex: "triggerRole",
    align: "center",
    ellipsis: true,
  },
  {
    title: "超时抄送人",
    dataIndex: "timeoutRole",
    align: "center",
    ellipsis: true,
  },
]);
const modalColumns = ref([
  {
    title: "SOP名称",
    dataIndex: "sopName",
    align: "center",
    ellipsis: true,
  },
  {
    title: "SOP步骤",
    dataIndex: "sopStep",
    align: "center",
    ellipsis: true,
  },
  {
    title: "解决角色",
    dataIndex: "solverRole",
    align: "center",
    ellipsis: true,
  },
  {
    title: "推进顺序",
    dataIndex: "sequence",
    align: "center",
    ellipsis: true,
  },
]);
//     新建模板
function handleAddTemplate() {
  currentTemplateData.value = {};
  templateState.isDetail = false;
  templateState.templateModalVisible = true;
}

const onSelectChange = (selectedRowKeys) => {
  console.log(selectedRowKeys, "selectedRowKeys");
  templateState.templateModalForm.selectedRowKeys = selectedRowKeys;
};
//     新增抄送设置
function handleAddCc() {
  templateState.templateModalForm.ccList?.push({
    warnLevel: undefined,
    role: undefined,
    timeouRole: undefined,
  });
}
function handleDeleteCc(index) {
  if (templateState.templateModalForm.ccList?.length <= 1) {
    return;
  }
  templateState.templateModalForm.ccList?.splice(index, 1);
}
const sopMbFormRef = ref(null);
const currentTemplateData = ref({});
function confirmGdTemplate() {
  sopMbFormRef.value
    .validate()
    .then(() => {
      templateState.okLoading = true;
      if (nodes.value.length == 0) {
        message.info("请先配置SOP步骤");
        return;
      }
      const selectedSopList = templateState.templateModalForm.sopList.filter(
        (item) =>
          templateState.templateModalForm.selectedRowKeys.includes(
            item.sopStepId
          )
      );
      const params = { ...templateState.templateModalForm };
      params.sopList = selectedSopList;
      let api = currentTemplateData.value.templateId ? put : post;
<<<<<<< HEAD
      api("/solution-ppm-work-order/api/v1/work_order_template", params)
=======
      api(
        "/solution-ppm/api/v2/built-in-system-ppm/work_order_template",
        params
      )
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
        .then((data) => {
          if (data.code !== 200) {
            message.error(data.message);
            return;
          }
          message.success(data.message);
          templateState.templateModalVisible = false;
          resetTemplateForm();
          getGdTemplateData();
        })
        .finally(() => {
          templateState.okLoading = false;
        });
    })
    .finally(() => {
      templateState.okLoading = false;
    });
}
function resetTemplateForm() {
  templateState.templateModalForm = {
    templateName: undefined, //sop名称
    finishStandard: undefined, //完成标准
    assessorStandard: undefined, //审核标准
    type: undefined, //工单类型
    monitorScene: undefined, //监控场景
    belongBusiness: undefined, //所属业务
    attachmentTemplateList: undefined, //附件名称
    WorkOrderTemplate: [], //勾选的sop
    ccList: [
      {
        warnLevel: undefined, //告警级别
        role: undefined, //触发抄送人角色
        timeouRole: undefined, //超市抄送角色
      },
    ],
    sopList: [],
    selectedRowKeys: [],
  };
  nodes.value = [];
  edges.value = [];
}
function cancelGdTemplate() {
  templateState.templateModalVisible = false;
  resetTemplateForm();
}
//     类型改变清空监控
function hanldeTypeChange(flag) {
  if (flag) {
    templateState.filter.monitorScene = undefined;
  } else {
    templateState.templateModalForm.monitorScene = undefined;
  }
}
// 编辑反显
async function handlerEditTemplate(record, isDetail) {
  isShowForm.value = false;
  templateState.modalTitle = isDetail ? "详情" : "编辑工单模板";
  templateState.isDetail = isDetail ? true : false;
  currentTemplateData.value = record;
  record.ccList.forEach((item) => {
    if (!item.timeoutRoleList) {
      item.timeoutRoleList = [];
    }
    if (!item.triggerRoleList) {
      item.triggerRoleList = [];
    }
  });
  // 先拷贝 record 的数据到表单
  Object.assign(templateState.templateModalForm, record);
  // 获取全部 SOP 数据
  await getMonitorSceneList(false);
<<<<<<< HEAD
  post("/solution-ppm-work-order/api/v1/work_order_sop/search", {
=======
  post("/solution-ppm/api/v2/built-in-system-ppm/work_order_sop/search", {
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
    workType: templateState.templateModalForm.type,
    monitorScene: templateState.templateModalForm.monitorScene,
  }).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    templateState.templateModalVisible = true;
    nodes.value = JSON.parse(data.data[0].flowChart).chartList.map((item) => {
      return {
        ...item,
        selected: false,
      };
    });

    edges.value = JSON.parse(data.data[0].flowChart).lineList.map((item) => {
      return {
        ...item,
        selected: false,
      };
    });
  });
}
function handlerDetailTemplate(id) {
  handlerEditTemplate(id, true);
}
// 删除sop
function handlerDeleteTemplate(id) {
<<<<<<< HEAD
  del(`/solution-ppm-work-order/api/v1/work_order_template/${id}`).then(
    (data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      message.success(data.message);
      getGdTemplateData();
    }
  );
}
// 下载文件的函数
function downLoadGdTemplateFile(item) {
  fetch(item.url)
    .then((response) => response.blob())
    .then((blob) => {
      const downloadLink = document.createElement("a");
      const url = URL.createObjectURL(blob);
      downloadLink.href = url;
      downloadLink.setAttribute("download", item.name);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);

      // Release the object URL after the download
      URL.revokeObjectURL(url);
      pageLoading.loading = false;
    })
    .catch((err) => {
      console.error("Download failed", err);
    });
}
// 打开图片的函数
function viewImage(url) {
  window.open(url, "_blank"); // 在新窗口打开图片
}
function groupSopData(data) {
  let currentSopName = "";

  // 遍历数据，计算每一行的 rowSpan
  return data.map((item, index) => {
    if (currentSopName !== item.sopName) {
      // 更新当前的标识符
      currentSopName = item.sopName;

      // 计算这个组的 rowSpan
      let rowSpan = 0;
      for (let i = index; i < data.length; i++) {
        const currentItem = data[i];
        if (currentSopName === currentItem.sopName) {
          rowSpan += 1;
        } else {
          break;
        }
      }
      item.rowSpan = rowSpan;
    } else {
      item.rowSpan = 0; // 如果是相同的组，重置 rowSpan
    }

    return item;
  });
}
//     上线/下线
function publishOffline(item, id) {
  put(`/solution-ppm-work-order/api/v1/work_order_template/${id}`).then(
    (data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      if (item.status == "待发布") {
        message.success("SOP模板发布成功");
      } else {
        message.success("SOP模板下线成功");
      }

      getGdTemplateData();
    }
  );
}
// 定制化代码
import { VueFlow, useVueFlow, Handle, Panel } from "@vue-flow/core";
const { fitView } = useVueFlow();
import { Background } from "@vue-flow/background";
import { Controls } from "@vue-flow/controls";
import "@vue-flow/core/dist/style.css";
import "@vue-flow/core/dist/theme-default.css";
import { Position } from "@vue-flow/core";
// 确保从正确路径导入 BaseEdge
import { BaseEdge } from "@vue-flow/core"; // 注意：不是 '@vue-flow/additional-components'
// import CustomEdge from './CustomEdge.vue'
import {
  getStraightPath,
  getBezierPath,
  getSmoothStepPath,
} from "@vue-flow/core";
import { backgroundColor } from "html2canvas/dist/types/css/property-descriptors/background-color";
// 🟢 1. 预配置节点列表
const presetNodes = [
  // { id: '1', type: 'start', targetPosition: Position.Bottom, data: { label: '开始' }, isStart: true },
  {
    id: "2",
    type: "input",
    sourcePosition: Position.Bottom,
    data: { label: "步骤" },
  },
  {
    id: "4",
    type: "output",
    targetPosition: Position.Top,
    data: { label: "结束" },
  },
];

// 🟢 2. 画布数据
const nodes = ref([]);
const edges = ref([]);
function getBacColor(props) {
  if (!props.data.sopStep || !props.data.solverRole) {
    return "1px soild red";
  } else {
    return "1px soild #e5e7eb";
  }
}
// 🟢 3. 节点配置弹窗
const selectedNode = ref({});
const isShowForm = ref(false);

// 节点点击 - 弹窗
const onNodeClick = (event, node) => {
  console.log(event);
  if (event.node.type === "input") {
    selectedNode.value = event.node.data;
    isShowForm.value = true;
  } else {
    selectedNode.value = {};
    isShowForm.value = false;
  }
};
=======
  del(
    `/solution-ppm/api/v2/built-in-system-ppm/work_order_template/${id}`
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    message.success(data.message);
    getGdTemplateData();
  });
}
// 下载文件的函数
function downLoadGdTemplateFile(item) {
  fetch(item.url)
    .then((response) => response.blob())
    .then((blob) => {
      const downloadLink = document.createElement("a");
      const url = URL.createObjectURL(blob);
      downloadLink.href = url;
      downloadLink.setAttribute("download", item.name);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);

      // Release the object URL after the download
      URL.revokeObjectURL(url);
      pageLoading.loading = false;
    })
    .catch((err) => {
      console.error("Download failed", err);
    });
}
// 打开图片的函数
function viewImage(url) {
  window.open(url, "_blank"); // 在新窗口打开图片
}
function groupSopData(data) {
  let currentSopName = "";

  // 遍历数据，计算每一行的 rowSpan
  return data.map((item, index) => {
    if (currentSopName !== item.sopName) {
      // 更新当前的标识符
      currentSopName = item.sopName;

      // 计算这个组的 rowSpan
      let rowSpan = 0;
      for (let i = index; i < data.length; i++) {
        const currentItem = data[i];
        if (currentSopName === currentItem.sopName) {
          rowSpan += 1;
        } else {
          break;
        }
      }
      item.rowSpan = rowSpan;
    } else {
      item.rowSpan = 0; // 如果是相同的组，重置 rowSpan
    }

    return item;
  });
}
//     上线/下线
function publishOffline(item, id) {
  put(
    `/solution-ppm/api/v2/built-in-system-ppm/work_order_template/${id}`
  ).then((data) => {
    if (data.code !== 200) {
      message.error(data.message);
      return;
    }
    if (item.status == "待发布") {
      message.success("SOP模板发布成功");
    } else {
      message.success("SOP模板下线成功");
    }

    getGdTemplateData();
  });
}
// 定制化代码
import { VueFlow, useVueFlow, Handle, Panel } from "@vue-flow/core";
const { fitView } = useVueFlow();
import { Background } from "@vue-flow/background";
import { Controls } from "@vue-flow/controls";
import "@vue-flow/core/dist/style.css";
import "@vue-flow/core/dist/theme-default.css";
import { Position } from "@vue-flow/core";
// 确保从正确路径导入 BaseEdge
import { BaseEdge } from "@vue-flow/core"; // 注意：不是 '@vue-flow/additional-components'
// import CustomEdge from './CustomEdge.vue'
import {
  getStraightPath,
  getBezierPath,
  getSmoothStepPath,
} from "@vue-flow/core";
import { backgroundColor } from "html2canvas/dist/types/css/property-descriptors/background-color";
import { log } from "console";
// 🟢 1. 预配置节点列表
const presetNodes = [
  // { id: '1', type: 'start', targetPosition: Position.Bottom, data: { label: '开始' }, isStart: true },
  {
    id: "2",
    type: "input",
    sourcePosition: Position.Bottom,
    data: { label: "步骤" },
  },
  {
    id: "4",
    type: "output",
    targetPosition: Position.Top,
    data: { label: "结束" },
  },
];

// 🟢 2. 画布数据
const nodes = ref([]);
const edges = ref([]);
function getBacColor(props) {
  if (!props.data.sopStep || !props.data.solverRole) {
    return "1px soild red";
  } else {
    return "1px soild #e5e7eb";
  }
}
// 🟢 3. 节点配置弹窗
const selectedNode = ref({});
const isShowForm = ref(false);

// 节点点击 - 弹窗
const onNodeClick = (event, node) => {
  console.log(event);
  if (event.node.type === "input") {
    selectedNode.value = event.node.data;
    isShowForm.value = true;
  } else {
    selectedNode.value = {};
    isShowForm.value = false;
  }
};
function handlePaneClick(a){
selectedNode.value = {};
    isShowForm.value = false;

}
>>>>>>> 3a56799eded2477af25490747235e794ed90d148
</script>
<style lang="less" scoped>
.page_root {
  width: 100%;
  height: 100%;
  overflow: auto;
}
.page_root :deep(.@{ant-prefix}-spin-nested-loading),
.page_root :deep(.@{ant-prefix}-spin-container) {
  height: 100%;
}
.page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
}
.page_root :deep(.@{ant-prefix}-table) {
  flex: auto;
  overflow: auto;
}
.table-moreBtn_down {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  width: 100px;
}

.table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
  background: #ebf1ff;
}

/*  表格树结构样式处理，展开按钮层级增加*/
:deep(.@{ant-prefix}-table-row-expand-icon) {
  z-index: 1;
}
/*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
:deep(
    .@{ant-prefix}-table-row-level-1
      .@{ant-prefix}-table-cell-with-append
      .cell-wrapper-left
  ) {
  left: 15px !important;
  width: calc(100% - 15px);
}
:deep(
    .@{ant-prefix}-table-row-level-2
      .@{ant-prefix}-table-cell-with-append
      .cell-wrapper-left
  ) {
  left: 30px !important;
  width: calc(100% - 30px);
}
:deep(
    .@{ant-prefix}-table-row-level-3
      .@{ant-prefix}-table-cell-with-append
      .cell-wrapper-left
  ) {
  left: 45px !important;
  width: calc(100% - 45px);
}
:deep(
    .@{ant-prefix}-table-row-level-4
      .@{ant-prefix}-table-cell-with-append
      .cell-wrapper-left
  ) {
  left: 60px !important;
  width: calc(100% - 60px);
}

/* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
:deep(.@{ant-prefix}-transfer-list) {
  height: 100%;
  width: 50%;
}
/*工单模板*/
.gd-template-body {
  height: 100%;
  overflow: hidden;
  background-color: #f0f2f5;
  .top-search {
    margin-bottom: 16px;
    border-radius: 4px;
    background-color: #fff;
    padding: 16px;
    padding-bottom: 0;
  }
  .template-content {
    height: 100%;
    padding: 16px 24px;
    background-color: #fff;
    .sop-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 16px;
      .sop-title-left {
        font-size: 16px;
        color: #262626;
        letter-spacing: 0;
        font-weight: 600;
        line-height: 16px;
        padding-left: 8px;
        border-left: 4px solid #3875ff;
        height: 16px;
      }
    }
    .gd-template-scroll {
      overflow-y: auto;
      overflow-x: hidden;
      height: calc(100% - 200px);
    }
  }
}

/*工单模板*/
.top-left {
  width: 100%;
  padding: 16px;
  background-color: #fff;
  border-radius: 4px;
}
.top-right {
  border-radius: 4px;
  background-color: #fff;
  padding: 20px 24px;
  padding-right: 36px;
}
.right-title {
  display: flex;
  margin-bottom: 8px;
}
.title-font {
  font-size: 14px;
  color: rgba(89, 89, 89, 0.65);
  letter-spacing: 0;
  text-align: center;
  font-weight: 400;
}

.right-icon {
  display: flex;
}
.min-div,
.left-icon {
  width: 40%;
  display: flex;
  gap: 8px;
}
.max-div,
.right-icon {
  flex: 1;
}
.max-div {
  text-align: left;
}

.right-icon-content {
  flex: 1;
  display: flex;
  justify-content: space-between;
}

.ceycle0,
.ceycle1,
.ceycle2,
.ceycle3 {
  width: 72px;
  height: 22px;
  color: #fff;
  text-align: center;
  line-height: 22px;
  font-weight: 600;
  border-radius: 2px;
}
.ceycle0 {
  background-color: #ff2a00;
}
.ceycle1 {
  background-color: #ffa940;
}
.ceycle2 {
  background-color: #ffa940;
}
.ceycle3 {
  background-color: #1890ff;
}
.ph-icon,
.xc-icon,
.zj-icon {
  width: 72px;
  height: 22px;
  color: #262626;
  text-align: center;
  line-height: 22px;
  font-weight: 600;
  background-color: #d6d6d6;
}
.tip {
  display: inline-block;
  width: 60px;
  position: absolute;
  bottom: -20px;
  left: -20px;
  text-align: center;
  font-weight: 800;
}
.main {
  background-color: #fff;
  height: 100%;
  border-radius: 4px;
  padding: 20px 24px;
  padding-top: 16px;
  position: relative;
}
.main-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
/*折叠面板样式*/

:deep(.ant3-collapse-header) {
  padding: 0 !important;
  border: none !important;
  color: #262626 !important;
  background: rgba(56, 117, 255, 0.1);
}

:deep(
    .ant3-collapse-borderless
      > .ant3-collapse-item
      > .ant3-collapse-content
      > .ant3-collapse-content-box
  ) {
  padding: 0 !important;
}

:deep(.ant3-collapse-item) {
  margin-bottom: 8px;
}

:deep(
    .ant3-collapse-icon-position-right
      > .ant3-collapse-item
      > .ant3-collapse-header
  ) {
  color: #3875ff;
  background: rgba(56, 117, 255, 0.1);
  position: relative;
  border-radius: 4px 4px 0 0;
}

/*折叠面板样式*/
.template-item-title {
  width: 100%;
  padding: 16px 24px;
  display: flex;
  flex-direction: column;
}
.item-top {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid #d9d9d9;
  padding-bottom: 16px;
}

.top-left-div {
  display: flex;
  gap: 8px;
  align-items: center;
}
.item-sign {
  width: 72px;
  height: 22px;
  padding: 0 8px;
  background-color: #3875ff;
  color: #fff;
  border-radius: 2px;
  line-height: 22px;
}
.item-name {
  font-size: 16px;
  color: #262626;
  letter-spacing: 0;
  font-weight: 500;
}
.top-right-div {
  display: flex;
  align-items: center;
}
.item-bottom {
  padding-top: 16px;
  display: flex;
}
.bottom-top-item:first-child {
  padding-right: 24px;
}
.bottom-top-item:nth-child(n + 2) {
  padding: 0 24px;
}
.bottom-top-item:not(:last-child):nth-last-child(n + 2) {
  border-right: 1px solid #d9d9d9;
}
.item-inner {
  padding: 16px 24px;
  background: #fff;
  border-radius: 0 0 4px 4px;
}
.inner-radio {
  margin-bottom: 16px;
}
.bottom-top-title {
  font-size: 14px;
  color: #595959;
  letter-spacing: 0;
  text-align: right;
  font-weight: 400;
}
.bottom-top-msg {
  font-size: 14px;
  color: #262626;
  letter-spacing: 0;
  font-weight: 500;
}
.item-bottom > * {
  align-self: flex-end; /* 内部元素底部对齐 */
}
.title-border {
  border-bottom: 1px solid #d9d9d9;
}

.active-icon {
  color: #3875ff;
  transform: rotate(90deg);
}

.pagination-div {
  position: absolute;
  right: 30px;
  bottom: 0;
  padding: 10px;
  background: transparent; /* 可选：为背景添加颜色 */
}

:deep(.ant3-collapse-item) {
  background: #ffffff;
}

.gd-item {
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.2);
  margin: 2px;
  margin-bottom: 24px;
}
.gd-item:last-child {
  margin-bottom: 5px;
}

.max-length {
  display: inline-block; /* 使得元素能够处理 overflow */
  max-width: 180px; /* 根据需要调整最大宽度 */
  overflow: hidden; /* 隐藏超出部分 */
  white-space: nowrap; /* 不换行 */
  text-overflow: ellipsis; /* 显示省略号 */
}
:deep(
    .ant3-collapse .ant3-collapse-item-disabled > .ant3-collapse-header,
    .ant3-collapse .ant3-collapse-item-disabled
  ) {
  cursor: default;
}
.inner-radio:deep(
    .ant3-radio-group-solid
      .ant3-radio-button-wrapper-checked:not(
        .ant3-radio-button-wrapper-disabled
      )
  ) {
  background: rgba(56, 117, 255, 0.2);
  color: #3875ff;
}

.inner-table:deep(.@{ant-prefix}-table-thead) > tr > th {
  background: #f7f8f9;
  color: #262626;
  font-weight: 600;
  padding: 8px 16px;
  border-right: 1px solid #d9d9d9 !important;
  position: relative;
}
.inner-table :deep(.@{ant-prefix}-table-tbody) tr > td {
  font-size: 14px;
  font-family: arial, helvetica, "microsoft yahei";
  font-weight: 400;
  color: #262626;
  border-bottom: 1px solid #d9d9d9;
  padding: 8px 16px;
  word-break: break-all;
}
.modal-sop-title {
  height: 16px;
  line-height: 16px;
  padding-left: 8px;
  border-left: 4px solid #3875ff;
  font-size: 16px;
  color: #262626;
  letter-spacing: 0;
  font-weight: 600;
  margin-bottom: 16px;
}
.sop-modal:deep(.ant3-form-item-label) {
  width: 115px;
}
.modal-table :deep(.@{ant-prefix}-table-thead) > tr > th {
  background: #3875ff;
  font-size: 14px;
  font-family: arial, helvetica, "microsoft yahei";
  font-weight: 600;
  color: #ffffff;
  border-bottom: 1px solid #3875ff;
  padding: 8px 16px;
}

.modal-table :deep(.@{ant-prefix}-table-tbody) tr > td {
  font-size: 14px;
  font-family: arial, helvetica, "microsoft yahei";
  font-weight: 400;
  color: #262626;
  padding: 8px 16px;
  word-break: break-all;
  .cell-wrapper {
    padding: 0 16px;
  }
}
.modal-table {
  margin-bottom: 16px;
}
.modal-sop-title-no {
  font-size: 14px;
  color: #262626;
  letter-spacing: 0;
  font-weight: 600;
  margin-bottom: 16px;
}
/* 全局容器样式 */
.flow-content {
  display: flex;
  flex-direction: column;
  height: 400px;
  overflow: auto;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  margin-bottom: 16px;
}

/* 顶部操作栏 */
.flow-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 24px;
  background-color: #fff;
  border-bottom: 1px solid #e8e8e8;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}

.flow-header-actions {
  display: flex;
  gap: 12px;
}

/* 主体容器 */
.flow-container {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* 左侧边栏 */
.sidebar {
  width: 85px;
  padding: 10px 0;
  overflow-y: auto;
  text-align: center;
  background: rgba(255, 255, 255, 0.8);
  margin: 5px;
  border: 1px solid rgba(56, 117, 255, 0.5);
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.2);
  border-radius: 4px;
  margin-right: 16px;
}

.draggable-node {
  padding: 10px 12px;
  color: #262626;
  cursor: grab;
  display: flex;
  gap: 8px;
  justify-content: space-between;
  align-items: center;
}

.draggable-node:hover {
  background: rgba(56, 117, 255, 0.1);
  border-color: #dee2e6;
}

/* 画布区域 */
.flow-area {
  flex: 1;
  position: relative;
  background-color: #f8f9fa;
  overflow: hidden;
  border-radius: 4px;
}
/* 节点样式 */
.custom-node {
  position: relative;
  height: 36px;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 14px;
  color: #fff;
  border: 2px solid #e5e7eb;
}
.node-content {
  position: absolute;
  bottom: -25px;
}
/* 不同类型节点颜色 */
.vue-flow__node-start .custom-node {
  background-color: #fff;
  border: 2px solid rgba(114, 228, 204, 1);
  color: #262626;
  width: 36px;
  border-radius: 50%;
}

.vue-flow__node-input .custom-node {
  background-color: #ffffff;

  color: #262626;
}

.vue-flow__node-output .custom-node {
  background-color: #fff;
  border: 2px solid rgba(254, 112, 112, 1);
  color: #262626;
  width: 36px;
  border-radius: 50%;
}
:deep(.vue-flow__node-output) {
  padding: 0;
  width: unset;
  border: none;
  border-radius: 50%;
}
:deep(.vue-flow__node-output.selected) {
  border: none;
  box-shadow: none;
}
.sop-modal :deep(.vue-flow__node-input) {
  padding: 0;
  border: none;
  box-shadow: none;
}
.sop-modal :deep(.vue-flow__node-input.selected) {
  border: none;
}
/* 节点选中状态 */
.vue-flow__node.selected .custom-node {
}

/* 节点删除按钮 */
.node-delete-btn {
  position: absolute;
  top: 8px;
  right: -24px;
  cursor: pointer;
}
/* 节点新增下一个按钮 */
.add-next-btn {
  position: absolute;
  top: -15px;
  right: 50px;
  width: 20px;
  height: 20px;
  background: #ff4d4f;
  color: white;
  border-radius: 50%;
  text-align: center;
  line-height: 20px;
  font-size: 12px;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  opacity: 1;
  transition: opacity 0.2s ease;
}
.node-add-btn {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 20px;
  height: 20px;
  background: #ff4d4f;
  color: white;
  border-radius: 50%;
  text-align: center;
  line-height: 20px;
  font-size: 12px;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  opacity: 1;
  transition: opacity 0.2s ease;
}

/* 连线样式 */
.vue-flow__edge-path {
  stroke: #888;
  stroke-width: 2;
}

.vue-flow__edge.selected .vue-flow__edge-path {
  stroke: #1890ff;
  stroke-width: 3;
}

/* 连线删除按钮 */
.edge-delete-fo {
  pointer-events: all;
}

.edge-delete-btn {
  width: 20px;
  height: 20px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  opacity: 1;
  transition: opacity 0.2s ease;
  position: relative;
}

/* 控制面板样式 */
.vue-flow__controls {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  border-radius: 6px;
  overflow: hidden;
}

.vue-flow__controls-button {
  background-color: #fff;
  border-bottom: 1px solid #f0f0f0;
  transition: background-color 0.2s ease;
}

.vue-flow__controls-button:hover {
  background-color: #f5f5f5;
}

.vue-flow__controls-button svg {
  fill: #595959;
}

/* 背景网格 */
.vue-flow__background {
  background-color: #f5f5f5;
}

/* 模态框样式 */
.ant-modal-header {
  border-bottom: 1px solid #f0f0f0;
}

.ant-modal-title {
  color: #333;
  font-weight: 500;
}

.ant-form-item-label > label {
  color: #595959;
}
.readonly-wrapper {
  pointer-events: none;
  opacity: 0.85; /* 可选，加点透明度提示是只读 */
  cursor: not-allowed;
}
.node-line {
  width: 150px;
  height: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  box-shadow: none;
  line-height: 32px;
  border-radius: 4px;
  padding: 0 5px;
}
.lf-node-selected {
  border: 1px dashed #8a94a5;
  padding: 1px;
  background-color: transparent;
  border-radius: 4px;
  opacity: 1;
}

.node-hover-wrapper {
  position: relative;
  display: inline-block;
  padding: 2px;
  background-color: #f5f5f5;
}
//选中状态
.node-hover-wrapper::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 1px dashed transparent;
  border-radius: 4px; /* 确保是矩形边框 */
  pointer-events: none; /* 不影响鼠标事件 */
  transition: border-color 0.2s;
}

.node-hover-active::after {
  border-color: rgba(24, 144, 255, 0.5);
}
.step-icon {
  width: 16px;
  height: 16px;
  background-color: #fff;
  border: 2px solid #d9d9d9;
  border-radius: 5px;
}
.end-icon {
  width: 16px;
  height: 16px;
  background-color: #fff;
  border: 2px solid rgba(254, 112, 112, 1);
  border-radius: 50%;
}
.no-data-msg {
  position: absolute;
  top: 61%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #595959;
}
.no-data-img {
  width: 66px;
  height: 80px;
  background-image: url("http://10.40.0.33:9001/file-storage/482099304502618112-source.png");
  background-size: cover;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>
